import Request from '@/js_sdk/luch-request/index.js'
import router from '@/router/index.js'
import {
	ACCESS_TOKEN,
	REFRESH_TOKEN
} from '@/utils/constant.js'

import systemConfig from '@/config'
import { toast } from '@/utils/common'
import store from '@/store/index.js';

let baseUrl = systemConfig.baseUrl;

// 请求队列
const requestQueue = {
	// 请求列表，存储刷新 token 期间发起的请求
	list: [],
	isRefreshing: false,
	// 添加请求
	add(config, resolve, reject, type) {
		this.list.push((newToken) => {
			if (newToken) {
				config.header['Access-Token'] = newToken
				// type标记是否需要重新发起请求，待token刷新后，继续请求即可，不带该属性token刷新后需要重新请求
				resolve(http.request(config))
			} else { // token不为真 表示 token 获取失败，清理队列请求的 Promise，避免内存堆积
				reject({
					status: 401,
					data: {
						code: 401
					},
					message: 'token已失效,请重新登录'
				})
			}
		})
	},
	// 执行队列
	execute(token) {
		let fn
		// eslint-disable-next-line
		while (fn = this.list.shift()) {
			fn(token)
		}
	},
	// 清空队列
	clear() {
		this.execute()
	}
}

function loginExpired(options) { // 两个token全部超时
	let timeout = setTimeout(toast('登录已过期'));
	store.dispatch('LogOut').then(() => {
		clearTimeout(timeout)
		uni.reLaunch({
			url: systemConfig.appInfo.app_type?'/pages/loginSSO':"/pages/login"
		})
	})
}

function handleByRefreshStatus(options) {
	return new Promise((resolve, reject) => {
		const status = requestQueue.refreshTokenStatus
		let {
			config
		} = options
		requestQueue.add(config, resolve, reject)
		if (!status) {
			getNewToken(options)
		}
	})
}

async function getNewToken(options) { // 获取新token
	try {
		if (requestQueue.refreshTokenStatus) {
			return false
		}
		requestQueue.refreshTokenStatus = true
		const refreshToken = store.getters['refreshToken']
		const token = store.getters['token']
		const res = await store.dispatch('RefreshToken') // 重新请求token
		requestQueue.refreshTokenStatus = false
		if (res.data.code === 200) {
			requestQueue.execute(res.data.result.token) // 使用新token重新请求
		} else {
			requestQueue.clear()
			loginExpired(options)
		}
	} catch (error) {
		console.log('error')
		requestQueue.refreshTokenStatus = false
		requestQueue.clear()
		loginExpired(options)
	}
}

const http = new Request()
http.setConfig((config) => {
	/* 设置全局配置 */
	config.baseURL = baseUrl /* 根域名不同 */
	config.header = {
		...config.header
	}
	return config
})

/**
 * 自定义验证器，如果返回true 则进入响应拦截器的响应成功函数(resolve)，否则进入响应拦截器的响应错误函数(reject)
 * @param { Number } statusCode - 请求响应体statusCode（只读）
 * @return { Boolean } 如果为true,则 resolve, 否则 reject
 */
// 有默认，非必写
http.validateStatus = (statusCode) => {
	return statusCode === 200
}
/* 请求之前拦截器 */
http.interceptors.request.use((config, cancel) => {
	
	// 添加Access-Token
	config.header = {
		...config.header,
		'Access-Token': store.getters['token']
	}
	
	// 请求参数增加页面菜单id,数据过滤使用- begin
	config.params = {
		_key:router.$Route?.meta?.key,
		_t:new Date().getTime(),
		...config.params,
	}
	// 请求参数增加页面菜单id,数据过滤使用- end
	return config
})

// 必须使用异步函数，注意
http.interceptors.response.use(async (response) => {
	/* 请求之后拦截器 */
	const {
		data
	} = response
	// console.log(response.config.url !== '/token/refresh')
	// if (data.code === 401 && response.config.url !== '/login') {
	// 	return handleByRefreshStatus(response)
	// }
	if (data.code && data.code !== 200) { // 服务端返回的状态码不等于200，则reject()
		toast(data.message)
	}
	return response
}, (response) => {
	// 请求错误做点什么
	console.log("请求错误做点什么", response);
	if (response && response) {
		let data = response.data
		const token = uni.getStorageSync(ACCESS_TOKEN)
		console.log("------异常响应------", token)
		console.log("------异常响应------", response)
		switch (response.statusCode) {
			case 403:
				toast('拒绝访问');
				break
			case 500:
				break
			case 404:
				break
			case 504:
				break
			case 401:
				return handleByRefreshStatus(response)
				break
			default:
				toast(data.message);
				break
		}
	}
	return response
})

export default http